package com.winner.dead_lock;

/**
 * 死锁是指多个进程循环等待彼此占有的资源
 * 如例, 第一个线程,占有资源a, 睡了2s, 第二个线程占有资源b.
 *
 * 产生死锁的四个条件:
 * 1. 互斥条件：即某个资源在一段时间内只能由一个进程占有，不能同时被两个或两个以上的进程占有
 * 2. 不可抢占条件：进程所获得的资源在未使用完毕之前，资源申请者不能强行的从资源占有者手中夺取资源，而只能由该资源的占有者进程自行释放
 * 3. 占有且等待条件：进程至少已经占有了一个资源，但又申请了一个新的被其他进程所占有的资源，此时处于等待状态
 * 4. 循环等待条件：若干个进程形成环形链，每个都占用对方申请的下一个资源
 *
 * 如何解决死锁: 1不能做, 因为线程安全就是互斥来做的, 破坏其他3个来解决死锁
 * 既然死锁的产生是两个线程无限等待对方持有的锁，那么只要等待时间有个上限不就好了。当然synchronized不具备这个功能，
 * 但是我们可以使用Lock类中的tryLock方法去尝试获取锁，这个方法可以指定一个超时时限，在等待超过该时限之后便会返回一个失败信息
 */
public class Host {
    public static void main(String[] args) {
//        String resourceA = "resourceA";
        Object a = new Object();
        Object b = new Object();
        get("11", () -> {
            System.out.println(11);
        });
        new Thread(()->{
            synchronized (a) { // 加锁
                System.out.println(Thread.currentThread().getName()+" i get a");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " i want get b");
                synchronized (b) { // 获取b资源的锁
                    System.out.println(Thread.currentThread().getName()+" i  get b"); // 因为产生了死锁, 这里的代码永远执行不到
                }
            }
        }).start();

        new Thread(()->{
            synchronized (b) {
                System.out.println(Thread.currentThread().getName()+" i get b");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+" i want get a");
                synchronized (a) { // 获取a资源的锁
                    System.out.println(Thread.currentThread().getName()+" i  get a"); // 因为产生了死锁, 这里的代码永远执行不到
                }
            }
        }).start();

//        打印结果
//        Thread-0i get a
//        Thread-1i get b
//        Thread-0i want get b
//        Thread-1i want get a
//        jps命令查看 4264 Host, jstack 4264查看死锁的报错

    }

    private static void get(String s, Runnable o) {

    }
}